package org.onvivals.common.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onvivals.common.config.properties.PermitAllUrlProperties;
import org.onvivals.common.web.Result;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Slf4j
@Configuration
@AllArgsConstructor
public class SaTokenConfigure {

    private final PermitAllUrlProperties permitAllUrlProperties;

    /**
     * 注册 Sa-Token全局过滤器
     */
    @Bean
    public SaServletFilter getSaReactorFilter() {
        return new SaServletFilter()
                // 拦截地址
                .addInclude("/**")
                // 开放地址
                .addExclude("/favicon.ico")
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    List<String> ignoreUrls = permitAllUrlProperties.getUrls();
                    // 登录认证：除白名单路径外均需要登录认证
                    SaRouter.match("/**").notMatch(ignoreUrls).check(StpUtil::checkLogin);
                })
                // 异常处理方法：每次setAuth函数出现异常时进入
                .setError(e -> {
                    log.info(e.getMessage());
                    return JSONUtil.parse(Result.error(HttpStatus.HTTP_UNAUTHORIZED, e.getMessage()));
                }) // 前置函数：在每次认证函数之前执行
                .setBeforeAuth(obj -> {
                    // ---------- 设置跨域响应头 ----------
                    SaHolder.getResponse()
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "3600")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*");

                    // 如果是预检请求，则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS).free(r -> log.warn("--------OPTIONS预检请求，不做处理")).back();
                });

    }
}
